package com.smart.village.big.screen.service.impl;

import com.smart.village.big.screen.domain.MergedPathsResponse;
import com.smart.village.big.screen.domain.NewsCategory;
import com.smart.village.big.screen.mapper.NewsCategoryMapper;
import com.smart.village.big.screen.service.AdminNewsCategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class AdminNewsCategoryServiceImpl implements AdminNewsCategoryService {
    @Autowired
    private NewsCategoryMapper newsCategoryMapper;

    public MergedPathsResponse mergePathsToRoot(List<String> leafNodeIds) {
        if (leafNodeIds == null || leafNodeIds.isEmpty())
            return MergedPathsResponse.error("请输入要处理的新闻分类ID列表");
        List<String> validIds = new ArrayList<>();
        List<String> invalidIds = new ArrayList<>();
        for (String id : leafNodeIds) {
            if (this.newsCategoryMapper.existsById(id) > 0) {
                validIds.add(id);
                continue;
            }
            invalidIds.add(id);
        }
        if (validIds.isEmpty())
            return MergedPathsResponse.error("请输入有效的新闻分类ID列表");
        List<List<NewsCategory>> allPaths = new ArrayList<>();
        for (String leafId : validIds) {
            List<NewsCategory> path = this.newsCategoryMapper.selectPathToRoot(leafId);
            if (!path.isEmpty())
                allPaths.add(path);
        }
        if (allPaths.isEmpty())
            return MergedPathsResponse.error("请输入有效的新闻分类ID列表");
        List<NewsCategory> mergedTrees = mergePaths(allPaths);
        return MergedPathsResponse.success(mergedTrees, validIds, invalidIds);
    }

    private List<NewsCategory> mergePaths(List<List<NewsCategory>> allPaths) {
        Map<String, NewsCategory> nodeMap = new HashMap<>();
        Set<String> allNodeIds = new HashSet<>();
        for (List<NewsCategory> path : allPaths) {
            for (NewsCategory node : path)
                allNodeIds.add(node.getNewsCategorySerialNumber());
        }
        for (String nodeId : allNodeIds) {
            NewsCategory node = (NewsCategory) this.newsCategoryMapper.selectById(nodeId);
            if (node != null)
                nodeMap.put(nodeId, createNodeCopy(node));
        }
        Map<String, List<NewsCategory>> childrenMap = new HashMap<>();
        for (NewsCategory node : nodeMap.values()) {
            String parentId = node.getParentSerialNumber();
            if (parentId != null && parentId.trim().isEmpty())
                parentId = null;
            if (parentId != null)
                ((List<NewsCategory>) childrenMap.computeIfAbsent(parentId, k -> new ArrayList())).add(node);
        }
        List<NewsCategory> rootNodes = (List<NewsCategory>) nodeMap.values().stream().filter(node -> {
            String parentId = node.getParentSerialNumber();
            return (parentId == null || parentId.trim().isEmpty() || !nodeMap.containsKey(parentId));
        }).map(this::createNodeCopy).collect(Collectors.toList());
        for (NewsCategory root : rootNodes)
            buildSubtreeRecursively(root, childrenMap, nodeMap);
        return rootNodes;
    }

    private void buildSubtreeRecursively(NewsCategory node, Map<String, List<NewsCategory>> childrenMap, Map<String, NewsCategory> nodeMap) {
        List<NewsCategory> children = childrenMap.getOrDefault(node.getNewsCategorySerialNumber(), new ArrayList<>());
        node.setChildren(new ArrayList());
        for (NewsCategory child : children) {
            if (nodeMap.containsKey(child.getNewsCategorySerialNumber())) {
                NewsCategory childCopy = createNodeCopy(child);
                node.getChildren().add(childCopy);
                buildSubtreeRecursively(childCopy, childrenMap, nodeMap);
            }
        }
    }

    private NewsCategory createNodeCopy(NewsCategory source) {
        NewsCategory copy = new NewsCategory();
        copy.setNewsCategorySerialNumber(source.getNewsCategorySerialNumber());
        copy.setNewsCategory(source.getNewsCategory());
        copy.setParentSerialNumber(source.getParentSerialNumber());
        copy.setNewsTerminal(source.getNewsTerminal());
        copy.setRowStatus(source.getRowStatus());
        copy.setOperationId(source.getOperationId());
        copy.setOperationDatetime(source.getOperationDatetime());
        copy.setCreaterSerialNumber(source.getCreaterSerialNumber());
        copy.setCreateDatetime(source.getCreateDatetime());
        copy.setChildren(new ArrayList());
        return copy;
    }
}
